#include "jobqueue.h"

JobQueue::JobQueue()
	:	nCompleted_ (0),
		nTotal_ (0)
{
	pthread_mutex_init(&queueMutex_, NULL);
	pthread_mutex_init(&nCompletedMutex_, NULL);
	pthread_mutex_init(&nTotalMutex_, NULL);
}

JobQueue::~JobQueue() {
	pthread_mutex_destroy(&queueMutex_);
	pthread_mutex_destroy(&nCompletedMutex_);
	pthread_mutex_destroy(&nTotalMutex_);
}

void JobQueue::push(Job *job) {
	pthread_mutex_lock(&queueMutex_);
	queue_.push(job);
	pthread_mutex_unlock(&queueMutex_);
	pthread_mutex_lock(&nTotalMutex_);
	++nTotal_;
	pthread_mutex_unlock(&nTotalMutex_);
}

Job *JobQueue::pop() {
	Job* job;
	pthread_mutex_lock(&queueMutex_);
	if (!queue_.empty()) {
		job = queue_.front();
		queue_.pop();
	}
	else
		job = NULL;
	pthread_mutex_unlock(&queueMutex_);
	return job;
}

void JobQueue::reset() {
	pthread_mutex_lock(&queueMutex_);
	// remove and destroy any remaining jobs
	while(!queue_.empty()) {
		delete queue_.front();
		queue_.pop();
	}
	pthread_mutex_unlock(&queueMutex_);
	
	pthread_mutex_lock(&nCompletedMutex_);
	nCompleted_ = 0;
	pthread_mutex_unlock(&nCompletedMutex_);
	
	pthread_mutex_lock(&nTotalMutex_);
	nTotal_ = 0;
	pthread_mutex_unlock(&nTotalMutex_);
}

void JobQueue::jobCompleted() {
	pthread_mutex_lock(&nCompletedMutex_);
	++nCompleted_;
	pthread_mutex_unlock(&nCompletedMutex_);
}

float JobQueue::getCompletion() {
	float completion;
	pthread_mutex_lock(&nCompletedMutex_);
	pthread_mutex_lock(&nTotalMutex_);
	completion = (float)nCompleted_ / (float)nTotal_;
	pthread_mutex_unlock(&nTotalMutex_);
	pthread_mutex_unlock(&nCompletedMutex_);
	return completion;
}

bool JobQueue::isCompleted() {
	bool isCompleted;
	pthread_mutex_lock(&nCompletedMutex_);
	pthread_mutex_lock(&nTotalMutex_);
	if (nCompleted_ == nTotal_)
		isCompleted = true;
	else
		isCompleted = false;
	pthread_mutex_unlock(&nTotalMutex_);
	pthread_mutex_unlock(&nCompletedMutex_);
	return isCompleted;
}

